﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

using RAP.Framework.Libary.Utils;
using RAP.Framework.Libary.DomTemplateBuilder.Element;
using RAP.Framework.Libary.DomTemplateBuilder.Element.Collection;
using RAP.Framework.Libary.DomTemplateBuilder.Interface;

namespace RAP.Framework.Libary.DomTemplateBuilder.Handler
{
  /// <summary>
  /// 迭代器的Handler
  /// </summary>
  public class IterateHandler : MutiplePropertyHandler
  {
    public const string ITERATE_CONEXT_KEY = "IterateContext";
    public const string ITERATE_CONEXT_PATH = "IterateContextPath";
    public const string ITERATE_CURRENT_INDEX = "ItemIndex";
    public const string ITERATE_CURRENT_COUNT = "ItemCount";
    public const string ITERATE_IS_FIRST = "IsFirst";
    public const string ITERATE_IS_LAST = "IsLast";
    public const string ITERATE_FIRST_ITEM = "FirstItem";
    public const string ITERATE_LAST_ITEM = "LastItem";
    public const string ITERATE_UPPER_FIELD = "Upper";
    public const string ITERATE_CURRENT_ITEM_FIELD = "Current";

    public new Iterate Element
    {
      get
      {
        return base.Element as Iterate;
      }
      set
      {
        base.Element = value as ElementBase;
      }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="propertyName"></param>
    /// <param name="rootParamObject"></param>
    /// <param name="parentParamObject"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    protected virtual IList GetPropertyListValue(string[] propertyNames, object rootParamObject, object parentParamObject, ITemplateRenderContext context)
    {
      var result = new ArrayList();
      if (propertyNames.IsNullOrEmpty())
      {
        propertyNames = new string[] { "@value" };//默认取父对象的值
      }
      foreach (var property in propertyNames)
      {
        if (property.StartsWith(Consts.CONST_FLAG))
        {
          var fieldName = property.LeftEndString(Consts.CONST_FLAG);
          result.Add(fieldName);
        }
        else
        {
          var listValue = GetPropertyValue(GetPropertyName(property, rootParamObject, parentParamObject, context), rootParamObject, parentParamObject, context);
          ICollection list = null;

          if (listValue is ICollection)
          {
            list = listValue as ICollection;
          }
          else if (listValue is String && listValue.IsNotNullOrEmpty())
          {
            list = listValue.ToString().Split(',').Map<string, string>((m) => m.Trim(), true).ToList();
          }
          else if (listValue is IDictionary)
          {
            list = (listValue as IDictionary).Values;
          }
          if (list.IsNullOrEmpty())
          {
            continue;
          }
          result.AddRange(list);
        }
      }
      return result;
    }

    /// <summary>
    /// 循环指定集合
    /// </summary>
    /// <param name="writer">output对象</param>
    /// <param name="list">集合</param>
    /// <param name="rootParamObject">根参数对象</param>
    /// <param name="parentParamObject">父节点参数对象</param>
    /// <param name="context">上下文对象</param>
    protected virtual void RenderCollection
    (
      StringBuilder writer
      , ICollection list
      , object rootParamObject
      , object parentParamObject
      , ITemplateRenderContext context
    )
    {
      //获取指定的集合元素的类型
      TypeCode itemValueType = Element.ItemValueType;
      var index = 0;
      var count = list.Count;
      var open = Element.Open;
      var close = Element.Close;
      var ignoreEmpty = Element.IgnoreEmpty;
      var renderChildNodes = Element.ChildNodes.Count > 0;
      var iterateContextPath = string.Empty;
      var property = Element.Property.IsNullOrEmptyValue(Element.HandlerName);
      var itemAlias = Element.ItemAlias;
      var isDistinctValue = Element.DistinctValue;
      var distinctValues = isDistinctValue ? new HashSet<string>(list.Count) : null;
      var enumrator = list.GetEnumerator();
      var startIndex = Element.StartIndex;
      var len = Element.Length;
      var endIndex = (len > 0 ? ((startIndex + len) < count ? startIndex + len : count - 1) : (count - 1));
      //设置当前上下文的upper（上一级）上下文对象的属性
      var values = new List<string>();

      #region 循环体
      while (enumrator.MoveNext())
      {
        if (index >= startIndex && index <= endIndex)
        {
          var iterateItem = enumrator.Current;
          IDictionary paramDic = null;
          if (iterateItem is IDictionary)
          {
            paramDic = iterateItem as IDictionary;
            paramDic[ITERATE_CURRENT_INDEX] = index;
          }
          context[ITERATE_CURRENT_INDEX] = index;
          context[ITERATE_IS_FIRST] = (index == startIndex);
          context[ITERATE_IS_LAST] = (index == endIndex);

          if (itemAlias.IsNotNullOrEmpty())
          {
            context[itemAlias] = iterateItem;
          }
          var value = string.Empty;
          if (renderChildNodes)
          {
            var sbTmp = new StringBuilder();
            base.DoRenderChildNodes(sbTmp, rootParamObject, iterateItem, context);
            value = sbTmp.ToString();
          }
          else
          {
            value = iterateItem != null ? iterateItem.ToString() : string.Empty;
          }
          if (iterateItem is IDictionary)
          {
            paramDic.RemoveKey(ITERATE_CURRENT_INDEX);
          }
          if (context.IsBreak)
          {
            break;
          }
          var convertedValue = value?.Trim().StartsWith(Consts.ALPHA_FLAG) == true ? value : GetConvertedValue(value, itemValueType);
          if (ignoreEmpty && (convertedValue == null || convertedValue.ToString().IsNullOrEmpty()))
          {
            index++;
            continue;
          }
          if (convertedValue != null)
          {
            value = convertedValue.ToString();
          }
          else
          {
            value = null;
          }
          if (isDistinctValue)
          {
            //去除重复值
            if (distinctValues.Contains(value))
            {
              continue;
            }
            distinctValues.Add(value);
          }
          values.Add(value);
        }
        index++;
      }
      #endregion 循环体

      try
      {
        if (itemAlias.IsNotNullOrEmpty())
        {
          context.Remove(itemAlias);
        }
        //从迭代器上下文对象中移除当前迭代器的上下文对象
      }
      catch
      { }

      if (values.Count > 0)
      {
        var resultValue = values.Join(Element.Conjunction);
        if (resultValue.IsNotNullOrEmpty())
        {
          //如果拼接后的字符串不为空字符串，则添加open，close和值
          if (open.IsNotNullOrEmpty())
          {
            writer.Append(open);
          }
          writer.Append(resultValue);
          if (close.IsNotNullOrEmpty())
          {
            writer.Append(close);
          }
        }
      }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="writer"></param>
    /// <param name="rootParamObject"></param>
    /// <param name="parentParamObject"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override void DoRender(StringBuilder writer, object rootParamObject, object parentParamObject, ITemplateRenderContext context)
    {
      var list = GetPropertyListValue(Property, rootParamObject, parentParamObject, context);
      if (list.IsNullOrEmpty())
      {
        return;
      }
      RenderCollection(writer, list, rootParamObject, parentParamObject, context);
    }
  }
}
